package com.fast.common.toolkit;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.ibatis.reflection.property.PropertyNamer;

import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Class LambdaTool
 *
 * @Auther: lhy
 * @Date: 2021/11/24 14:42
 * @Mail: 190643201@qq.com
 */
public class LambdaTool<T> {
    private Map<String, ColumnCache> columnMap = null;
    private boolean initColumnMap = false;

    public String columnsToString(SFunction<T, ?>... columns) {
        return this.columnsToString(true, columns);
    }

    protected String columnsToString(boolean onlyColumn, SFunction<T, ?>... columns) {
        return (String) Arrays.stream(columns).map((i) -> {
            return this.columnToString(i, onlyColumn);
        }).collect(Collectors.joining(","));
    }

    public String columnToString(SFunction<T, ?> column) {
        return this.columnToString(column, true);
    }

    protected String columnToString(SFunction<T, ?> column, boolean onlyColumn) {
        ColumnCache cache = this.getColumnCache(column);
        return onlyColumn ? cache.getColumn() : cache.getColumnSelect();
    }

    protected ColumnCache getColumnCache(SFunction<T, ?> column) {
        LambdaMeta meta = LambdaUtils.extract(column);
        String fieldName = PropertyNamer.methodToProperty(meta.getImplMethodName());
        Class<?> instantiatedClass = meta.getInstantiatedClass();
        this.tryInitCache(instantiatedClass);
        return this.getColumnCache(fieldName, instantiatedClass);
    }

    private void tryInitCache(Class<?> lambdaClass) {
        if (!this.initColumnMap) {
            this.columnMap = LambdaUtils.getColumnMap(lambdaClass);
            Assert.notNull(this.columnMap, "can not find lambda cache for this entity [%s]", new Object[]{lambdaClass.getName()});
            this.initColumnMap = true;
        }

    }

    private ColumnCache getColumnCache(String fieldName, Class<?> lambdaClass) {
        ColumnCache columnCache = (ColumnCache)this.columnMap.get(LambdaUtils.formatKey(fieldName));
        Assert.notNull(columnCache, "can not find lambda cache for this property [%s] of entity [%s]", new Object[]{fieldName, lambdaClass.getName()});
        return columnCache;
    }



}
